/*----------------------------------------------------------------------------
 *      Name:    Sim.ini
 *      Purpose: Functions used for simulating peripherals
 *      Version: V1.0
 *----------------------------------------------------------------------------
 *      This file is part of the uVision/ARM development tools.
 *      This software may only be used under the terms of a valid, current,
 *      end user licence from KEIL for a compatible version of KEIL software
 *      development tools. Nothing else gives you the right to use it.
 *
 *      Copyright (c) 2005-2007 Keil Software.
 *---------------------------------------------------------------------------*/

/*----------------------------------------------------------------------------
 * caculate the values for the UART Devisor Latch LSB and MSB register
 *---------------------------------------------------------------------------*/
func void baudrate (void) { 
  printf ("baudrate   9600 dll 0x%X\n", ((14400000UL / 16UL) + ( 9600-1))  /   9600);
  printf ("baudrate  14400 dll 0x%X\n", ((14400000UL / 16UL) + ( 14400-1)) /  14400);
  printf ("baudrate  19200 dll 0x%X\n", ((14400000UL / 16UL) + ( 19200-1)) /  19200);
  printf ("baudrate  38400 dll 0x%X\n", ((14400000UL / 16UL) + ( 38400-1)) /  38400);
  printf ("baudrate  57600 dll 0x%X\n", ((14400000UL / 16UL) + ( 57600-1)) /  57600);
  printf ("baudrate 115200 dll 0x%X\n", ((14400000UL / 16UL) + (115200-1)) / 115200);
} 


/*----------------------------------------------------------------------------
 *  Simulate LCD Display (2 line 40 character Text LCD with 4-bit Interface)
 *    Pins:
 *      - DB4..DB7 = P1.24..P1.27
 *      - RS       = P1.28
 *      - RW       = P1.29
 *      - E        = P1.31
 *---------------------------------------------------------------------------*/

define unsigned long oldPORT1;
define unsigned char Cursor;
define unsigned char bitpos;
define unsigned char Cmd;

define unsigned long _E;
define unsigned long _RW;
define unsigned long _RS;
define unsigned long _CTRL;
define unsigned long _DATA;

define unsigned char DataShift;
define unsigned long LCDMem;

MAP 0x10000000, 0x1000004F READ WRITE   // LCD Memory

DataShift = 24;         // shift data to 0 position
LCDMem    = 0x10000000; // memory to display LCD

oldPORT1 = PORT1;
Cursor   = 0;
bitpos   = 0;

_E    = 0x80000000;
_RW   = 0x20000000;
_RS   = 0x10000000;
_CTRL = 0xB0000000;
_DATA = 0x0F000000;

// Clear Display Function
Func void LCD_Clear (void) {
  unsigned char i;

  for (i = 0; i < 80; i++) {
//    _WBYTE(LCDMem + i, 0x20);
    _WBYTE(LCDMem + i, 0x0);
  }
  Cursor = 0;
}

// LCD Display Signal Function
Signal void LCD_Display (void) {
  unsigned char val;

  while (1) {
    wwatch(PORT1);  // Wait for write to PORT1
    if ((PORT1 & _RW) == 0) {
      // Write to Display
      if (((oldPORT1 & _E) != 0) && ((PORT1 & _E) == 0)) {
        // E: 1->0
        if ((PORT1 & _RS) == 0) {
          // Write Command
          val  = ((PORT1 & _DATA) >> DataShift);
          if (val == 3) {
            bitpos = 4;
          }
          Cmd &= 0xF0 >> bitpos;
          Cmd |= val << bitpos;
          if (bitpos == 0) {
            if (Cmd == 0x01) {
              // Clear Display
              LCD_Clear();
            } else if (Cmd & 0x80) {
              // Set Cursor Position
              Cursor = Cmd & 0x7F;
            }
          }
        } else {
          // Write Data
          val  = _RBYTE(LCDMem + Cursor);
          val &= 0xF0 >> bitpos;
          val |= ((PORT1 & _DATA) >> DataShift) << bitpos;
          _WBYTE(LCDMem + Cursor, val);
          if (bitpos == 0) Cursor++;
        }
        bitpos ^= 4;
      }
    } else {
      // Read from Display
      if (((oldPORT1 & _E) == 0) && ((PORT1 & _E) != 0)) {
        // E: 0->1
        if ((PORT1 & _RS) == 0) {
          // Read Status
          val = (0x7F >> bitpos) & 0x0F;
        } else {
          // Read Pointer
          val = ((Cursor & 0x7F) >> bitpos) & 0x0F;
        }
        PORT1 &= ~_DATA;
        PORT1 |=  val << DataShift;
        bitpos ^= 4;
      }
    }
    oldPORT1 = PORT1;
  }
}

LCD_Display()
